<?php
/**
 * CreateUser: zlh
 * CreateTime: 2022/2/5 18:15
 * Remark:
 */

namespace App\Http\Controllers;

use App\Consts\RedisConsts\RedisConsts;
use App\Consts\ResponseConsts\ResponseStatusConsts;
use App\Func\EncryptionFunc;
use App\Func\PathFunc;
use App\Func\ResponseFunc;
use App\Func\TokenFuc;
use App\Http\pkConfig\login\PkLoginConfigGet;
use App\Http\Requests\File\ExportExcelRequest;
use App\Http\Requests\ListBasicRequest;
use App\Models\File\FileModel;
use App\Models\MeClient\MeClientModel;
use App\Models\MeLawCase\MeLawCaseLawLetterModel;
use App\Tools\DingTalk\DingTalkUploadFacade;
use App\Tools\DocxGenerator\FormatDocx;
use App\Tools\File\ExcelFile;
use Darabonba\GatewaySpi\Models\InterceptorContext\request;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Storage;
use PHPUnit\Exception;
use setasign\Fpdi\Fpdi;

class FileController extends Controller
{
    private $cFile;
    public function __construct()
    {
        $this->cFile = ((app()->gcHelper->m_cFile))();
    }


    public function getFileInfo($fileId){
        $fileModel = new FileModel();
        $fileInfo = $fileModel->getFileById($fileId) ?? [];
        if($fileInfo){
            return ResponseFunc::returnJson(
                'ok',
                $fileInfo,
                '获取详情成功',
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }
    }

    private function getMimeTypeBySuffix($fileSuffix){
        $mimeArray = [
            "aac"=> "audio/aac",	// AAC audio
            "abw"=> "application/x-abiword",	// AbiWord document
            "arc"=> "application/x-freearc",	// Archive document (multiple files embedded)
            "avi"=> "video/x-msvideo",	// AVI=> Audio Video Interleave
            "azw"=> "application/vnd.amazon.ebook",	// Amazon Kindle eBook format
            "bin"=> "application/octet-stream",	// Any kind of binary data
            "bmp"=> "image/bmp",	// Windows OS/2 Bitmap Graphics
            "bz"=> "application/x-bzip",	// BZip archive
            "bz2"=> "application/x-bzip2",	// BZip2 archive
            "csh"=> "application/x-csh",	// C-Shell script
            "css"=> "text/css",	// Cascading Style Sheets (CSS)
            "csv"=> "text/csv",	// Comma-separated values (CSV)
            "doc"=> "application/msword",	// Microsoft Word
            "docx"=> "application/vnd.openxmlformats-officedocument.wordprocessingml.document",	// Microsoft Word (OpenXML)
            "eot"=> "application/vnd.ms-fontobject",	// MS Embedded OpenType fonts
            "epub"=> "application/epub+zip",	// Electronic publication (EPUB)
            "gif"=> "image/gif",	// Graphics Interchange Format (GIF)
            "htm"=> "text/html",
            "html"=> "text/html",	// HyperText Markup Language (HTML)
            "ico"=> "image/vnd.microsoft.icon",	// Icon format
            "ics"=> "text/calendar",	// iCalendar format
            "jar"=> "application/java-archive",	// Java Archive (JAR)
            "jpeg"=> "image/jpeg",
            "jpg"=> "image/jpeg",	// JPEG images
            "js"=> "text/javascript",	// JavaScript
            "json"=> "application/json",	// JSON format
            "jsonld"=> "application/ld+json",	// JSON-LD format
            "mid"=> "audio/midi audio/x-midi",
            "midi"=> "audio/midi audio/x-midi",	// Musical Instrument Digital Interface (MIDI)
            "mjs"=> "text/javascript",	// JavaScript module
            "mp3"=> "audio/mpeg",	// MP3 audio
            "mpeg"=> "video/mpeg",	// MPEG Video
            "mpkg"=> "application/vnd.apple.installer+xml",	// Apple Installer Package
            "odp"=> "application/vnd.oasis.opendocument.presentation",	// OpenDocument presentation document
            "ods"=> "application/vnd.oasis.opendocument.spreadsheet",	// OpenDocument spreadsheet document
            "odt"=> "application/vnd.oasis.opendocument.text",	// OpenDocument text document
            "oga"=> "audio/ogg",	// OGG audio
            "ogv"=> "video/ogg",	// OGG video
            "ogx"=> "application/ogg",	// OGG
            "otf"=> "font/otf",	// OpenType font
            "png"=> "image/png",	// Portable Network Graphics
            "pdf"=> "application/pdf",	// Adobe Portable Document Format (PDF)
            "ppt"=> "application/vnd.ms-powerpoint",	// Microsoft PowerPoint
            "pptx"=> "application/vnd.openxmlformats-officedocument.presentationml.presentation",	// Microsoft PowerPoint (OpenXML)
            "rar"=> "application/x-rar-compressed",	// RAR archive
            "rtf"=> "application/rtf",	// Rich Text Format (RTF)
            "sh"=> "application/x-sh",	// Bourne shell script
            "svg"=> "image/svg+xml",	// Scalable Vector Graphics (SVG)
            "swf"=> "application/x-shockwave-flash",	// Small web format (SWF) or Adobe Flash document
            "tar"=> "application/x-tar",	// Tape Archive (TAR)
            "tif"=> "image/tiff",
            "tiff"=> "image/tiff",	// Tagged Image File Format (TIFF)
            "ttf"=> "font/ttf",	// TrueType Font
            "txt"=> "text/plain",	// Text, (generally ASCII or ISO 8859-n)
            "vsd"=> "application/vnd.visio",	// Microsoft Visio
            "wav"=> "audio/wav",	// Waveform Audio Format
            "weba"=> "audio/webm",	// WEBM audio
            "webm"=> "video/webm",	// WEBM video
            "webp"=> "image/webp",	// WEBP image
            "woff"=> "font/woff",	// Web Open Font Format (WOFF)
            "woff2"=> "font/woff2",	// Web Open Font Format (WOFF)
            "xhtml"=> "application/xhtml+xml",	// XHTML
            "xls"=> "application/vnd.ms-excel",	// Microsoft Excel
            "xlsx"=> "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",	// Microsoft Excel (OpenXML)
            "xml"=> [
                "application/xml",//  代码对普通用户来说不可读 (RFC 3023, section 3)
                "text/xml" 	// XML 代码对普通用户来说可读 (RFC 3023, section 3)
            ],
            "xul"=> "application/vnd.mozilla.xul+xml",	// XUL
            "zip"=> "application/zip",	// ZIP archive
            "7z"=> "application/x-7z-compressed",	// 7-zip archive
        ];
        return @$mimeArray[$fileSuffix];
    }

    /**
     * 文件上传
     * @return \Illuminate\Http\JsonResponse
     */
    public function uploadFile(): \Illuminate\Http\JsonResponse
    {
        $fileModel = new FileModel();
        $allow = [
            'pdf',
            'jpg',
            'png',
            'gif',
            'doc',
            'docx',
            'zip',
            '7z',
            'rar',
            'txt',
            'xlsx',
            'xls'
        ];
        // 获取文件
        $file = request()->file('file');
        $hasExtra = @request()->get('extra');
        $formatExtra = [];
        if($hasExtra){
            $formatExtra = json_decode($hasExtra,true);
        }
        try {
            // 获取文件原始名称
            $originalName = $file->getClientOriginalName();
            // 获取文件临时存储位置
            $path = $file->getRealPath();
            // 获取mimeType
            $mimeType = $file->getMimeType();
            // 获取文件后缀名
            $ext = $file->getClientOriginalExtension();
            // 校验文件MimeType
            $extMimeType = $this->getMimeTypeBySuffix($ext);
            $err = $file->getError();
            if($err){
                return ResponseFunc::returnJson(
                    'error',
                    null,
                    '文件上传失败',
                    ResponseStatusConsts::OK_200_RESPONSE_STATUS
                );
            }
        }catch (\Exception $exception){
            return ResponseFunc::returnJson(
                'error',
                null,
                '文件上传失败',
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }

//        dump($ext);
//        dump($mimeType);
//        dd($extMimeType);
//        if($extMimeType != $mimeType){
//            return ResponseFunc::returnJson(
//                'error',
//                null,
//                '上传文件失败,文件类型错误',
//                ResponseStatusConsts::OK_200_RESPONSE_STATUS
//            );
//        }
        // 生成文件夹
        $dir = date("Ymd");
        // 生成加密后的文件地址
        $encryptionFileUrl = "file".DIRECTORY_SEPARATOR.$dir.DIRECTORY_SEPARATOR.md5($originalName.time()).".".$ext;
        if(!in_array($ext,$allow)){
            return ResponseFunc::returnJson(
                'error',
                null,
                '文件类型错误',
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }

        try {
            $res = Storage::disk('local')->put($encryptionFileUrl,file_get_contents($path));
            if(!$res){
                return ResponseFunc::returnJson(
                    'error',
                    null,
                    '上传文件失败',
                    ResponseStatusConsts::OK_200_RESPONSE_STATUS
                );
            }
            DB::beginTransaction();
            try {
                $id = $fileModel->insertGetId(
                    # 2022 - 7 7 新增发起人追溯
                    [
                        'owner_id' => TokenFuc::getCurrentStaffInfo()['staff_id'],
                        'file_name'=>$originalName,
                        'file_url'=>$encryptionFileUrl,
                        'file_ext'=>$ext,
                        'file_mime_type' => $mimeType,
                        'created_at' => time()
                    ]
                );
                # 如果需要上传至钉钉
                if($formatExtra) {
                    $res = $this->cFile->setFileToDingTalk(
                        fileId: $id,
                        parentSpaceName: $formatExtra['type'],
                        createSpaceName: $formatExtra['id']
                    );

                    # 更新
                    $dingTalkSpaceInfo = json_encode([
                        'spaceId' => $res->spaceId,
                        'fileName' => $res->fileName,
                        'fileSize' => $res->fileSize,
                        'fileType' => $res->fileType,
                        'fileId' => $res->fileId,
                    ]);
                    $updateFile = $fileModel->where('file_id', $id)
                        ->update([
                            'dingTalkSpaceInfo' => $dingTalkSpaceInfo
                        ]);
                }
                DB::commit();
            }catch (Exception $exception){
                DB::rollBack();
                return ResponseFunc::returnJson(
                    'error',
                    null,
                    $exception->getMessage(),
                    ResponseStatusConsts::OK_200_RESPONSE_STATUS
                );
            }


            return ResponseFunc::returnJson(
                'ok',
                [
                    'file_id' => $id,
                    'file_name'=>$originalName,
                    'file_url'=>$encryptionFileUrl,
                    'file_ext'=>$ext,
                    'file_mime_type' => $mimeType,
                    'created_at' => time()
                ],
                '上传文件成功',
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }catch (Exception $error){
            return ResponseFunc::returnJson(
                'error',
                null,
                $error->getMessage(),
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }
    }


    /**
     * 文件上传
     * @return \Illuminate\Http\JsonResponse
     */
    public function uploadFormatFile(): \Illuminate\Http\JsonResponse
    {
        $fileModel = new FileModel();

        $allow = [
            'doc',
            'docx'
        ];

        // 获取文件
        $file = request()->file('file');

        // 获取文件原始名称
        $originalName = $file->getClientOriginalName();
        // 获取文件临时存储位置
        $path = $file->getRealPath();
        // 获取mimeType

        $mimeType = $file->getMimeType();
        // 获取文件后缀名
        $ext = $file->getClientOriginalExtension();
        // 生成文件夹
        $time = time();
        $dir = date("Ymd",$time);

        // 生成加密后的文件地址
        $encryptionFileUrl = "templateFormat".DIRECTORY_SEPARATOR.$dir.DIRECTORY_SEPARATOR.md5($originalName.$time).".".$ext;
        if(!in_array($ext,$allow)){
            return ResponseFunc::returnJson(
                'error',
                null,
                '文件类型错误',
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }

        try {
            $res = Storage::disk('local')->put($encryptionFileUrl,file_get_contents($path));
            if(!$res){
                return ResponseFunc::returnJson(
                    'error',
                    null,
                    '上传文件失败',
                    ResponseStatusConsts::OK_200_RESPONSE_STATUS
                );
            }
            $id = $fileModel->insertGetId(
                [
                    'file_name'=>$originalName,
                    'file_url'=>$encryptionFileUrl,
                    'file_ext'=>$ext,
                    'file_mime_type' => $mimeType,
                    'created_at' => $time
                ]
            );
            return ResponseFunc::returnJson(
                'ok',
                [
                    'file_id' => $id,
                    'file_name'=>$originalName,
                    'file_url'=>$encryptionFileUrl,
                    'file_ext'=>$ext,
                    'file_mime_type' => $mimeType,
                    'created_at' => $time
                ],
                '上传文件成功',
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }catch (Exception $error){
            return ResponseFunc::returnJson(
                'error',
                null,
                $error->getMessage(),
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }
    }

    /**
     * 仅仅允许上传文件名
     * @return \Illuminate\Http\JsonResponse
     */
    public function uploadLetterFile(){
        $data =request()->all();
        $type = $data['type'] ?? 1;
        $lawCaseTempTypeStr = 'client_temp_law_filename';
        switch ($type){
            case 2:
                break;
        }

        $fileModel = new FileModel();

        $allow = [
            'docx'
        ];

        // 获取文件
        $file = request()->file('file');

        // 获取文件原始名称
        $originalName = $file->getClientOriginalName();
        // 获取文件临时存储位置
        $path = $file->getRealPath();
        // 获取mimeType

        $mimeType = $file->getMimeType();
        // 获取文件后缀名
        $ext = $file->getClientOriginalExtension();
        // 生成文件夹
        $time = time();
        $dir = date("Ymd",$time);

        // 生成加密后的文件地址
        $encryptionFileUrl = "defaultTemplate".DIRECTORY_SEPARATOR.$originalName;

        if(!in_array($ext,$allow)){
            return ResponseFunc::returnJson(
                'error',
                null,
                '仅允许上传docx',
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }

        try {
            $res = Storage::disk('local')->put($encryptionFileUrl,file_get_contents($path));
            $filePath = storage_path('app/' . $encryptionFileUrl);
            chmod($filePath, 0755);
            if(!$res){
                return ResponseFunc::returnJson(
                    'error',
                    null,
                    '上传文件失败',
                    ResponseStatusConsts::OK_200_RESPONSE_STATUS
                );
            }
            $id = $fileModel->insertGetId(
                [
                    'file_name'=>$originalName,
                    'file_url'=>$encryptionFileUrl,
                    'file_ext'=>$ext,
                    'file_mime_type' => $mimeType,
                    'created_at' => $time
                ]
            );

            return ResponseFunc::returnJson(
                'ok',
                [
                    'file_id' => $id,
                    'file_name'=>$originalName,
                    'file_url'=>$encryptionFileUrl,
                    'file_ext'=>$ext,
                    'file_mime_type' => $mimeType,
                    'created_at' => $time
                ],
                '上传文件成功',
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }catch (Exception $error){
            return ResponseFunc::returnJson(
                'error',
                null,
                $error->getMessage(),
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }
    }



    /**
     * 文件下载
     * @param $filePath
     */
    public function downloadFile(int $fileId)
    {
        $data =  request()->all();
        // Trans-toc
        $code1 = $data['utk'];
        // 解密token
        // 通过Rsa解密获取redis中正确的key
        $encryptionFunc = new EncryptionFunc();
        $adminLoginPkConfig = new PkLoginConfigGet();
        $redisKey = $encryptionFunc->rsaToBase64Decode($adminLoginPkConfig->getPrKey(),$code1);
        $isExist = Redis::exists($redisKey);
        if($isExist){
            $staffInfo = unserialize(Redis::get($redisKey));
        }else{
            return ResponseFunc::returnJson(
                'error',
                null,
                "缺少权限，下载失败",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }
        $fileModel = new FileModel();
        $fileInfo = $fileModel->where('file_id',$fileId)->first();
        return Storage::download($fileInfo['file_url'], $fileInfo['file_name']);
    }

    /**
     * @param int $fileId
     * @return \Illuminate\Http\JsonResponse
     */
    public function wordToPdf(int $fileId): \Illuminate\Http\JsonResponse
    {
        $fileModel = new FileModel();
        $fileInfo = $fileModel->where('file_id',$fileId)->first();
        if($fileInfo['file_ext'] != "docx" && $fileInfo['file_ext'] != "doc" ){
            return ResponseFunc::returnJson(
                'error',
                null,
                "当前文件不能进行转换",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }
        $path = FormatDocx::wordToPdf(
           $fileInfo['file_url'],
           $fileInfo['file_name']
        );
        return ResponseFunc::returnJson(
            'ok',
            [
                "file_id" => $this->insertFilePdf($path['newPath'],$fileId)
            ],
            "转换成功",
            ResponseStatusConsts::OK_200_RESPONSE_STATUS
        );
    }

    public function wordToHtml(int $fileId): \Illuminate\Http\JsonResponse
    {
        $fileModel = new FileModel();
        $fileInfo = $fileModel->where('file_id',$fileId)->first();
        if($fileInfo['file_ext'] != "docx" || $fileInfo['file_ext'] != "doc" ){
            return ResponseFunc::returnJson(
                'error',
                null,
                "当前文件不能进行转换",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }
        $fileName = $fileInfo['file_name'];
        $path = FormatDocx::wordToHtml(
            PathFunc::getStorageApp().$fileInfo['file_url'],
            $fileName
        );
        return ResponseFunc::returnJson(
            'ok',
            [
                "file_id" => $this->insertFileHtml($path['newPath'],$fileId)
            ],
            "转换成功",
            ResponseStatusConsts::OK_200_RESPONSE_STATUS
        );
    }

    /**
     * 水印添加方法
     * @param $fileUrl
     * @param string $watermarkText
     * @throws \setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException
     * @throws \setasign\Fpdi\PdfParser\Filter\FilterException
     * @throws \setasign\Fpdi\PdfParser\PdfParserException
     * @throws \setasign\Fpdi\PdfParser\Type\PdfTypeException
     * @throws \setasign\Fpdi\PdfReader\PdfReaderException
     */
    public function displayPdf($fileId){
        $data =  request()->all();
        // Trans-toc
        $code1 = $data['code1'];
        // Trans-top-v2
        $code2 = $data['code2'];
        $isExist = Redis::exists($code1);
        if($isExist){
            $staffInfo = unserialize(Redis::get($code1));
        }else{
            return ResponseFunc::returnJson(
                'error',
                null,
                "缺少权限，下载失败",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }
        if(!app()->gcHelper->gfVerifyUserTokenOK($staffInfo['staff_id'],$code2)){
            return ResponseFunc::returnJson(
                'error',
                null,
                "缺少权限，下载失败",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS
            );
        }

        $fileModel = new FileModel();
        $fileUrl = storage_path("app/".$fileModel->getFileById($fileId)['file_url']);
        $pdf = new Fpdi();

        //        $pdf->AddPage();
        //        $pdf->Write(7, 'ROOT_ICO');
        // set the source file
        $pageCount = $pdf->setSourceFile($fileUrl);;
        //遍历所有页面
        for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++){
            //导入页面
            $templateId = $pdf->importPage($pageNo);
            //获取导入页面的大小
            $size = $pdf->getTemplateSize($templateId);
            //创建页面（横向或纵向取决于导入的页面大小）
            if ($size['width'] > $size['height']){
                $pdf->AddPage('L', array($size['width'], $size['height']));
            }else {
                $pdf->AddPage('P', array($size['width'], $size['height']));
            }
            //使用导入的页面
            $pdf->useTemplate($templateId);
            if(false){//文字水印
                //设置字体
                //$pdf->SetFont('Arial','B','24');
                $family = ['courier', 'helvetica', 'times', 'symbol', 'zapfdingbats'];
                $pdf->SetFont('helvetica','U','50');
                //设置位置 - 加在中间位置
                $center_x = $size['width']/2;
                $center_y = $size['height']/2;
                $pdf->SetXY($center_x, $center_y);
                //写入水印 - 中文会乱码 建议使用中文图片
                $pdf->Write(7, 'ROOT_ICO');
            }else{//图片水印
                $center_x = $size['width']/2 - 40;$center_y = $size['height']/2;
                $pdf->image(__DIR__."/defaultWatermark-wl.png", 0, 0,210);//全屏背景水印
            }
        }
        //I输出output，D下载download，F保存file_put_contents，S返回return
//        $pdf->Output('F','Upload/all_to_path/report_file/save.pdf',false);
        $pdf->Output();
    }

    public function insertFileHtml($url,$parentId){
        $fileModel = new FileModel();
        $time = time();
        return $fileModel->insertGetId(
            [
                'file_name'=>md5($time.$parentId).".html",
                'file_url'=>$url,
                'file_ext'=>"html",
                'file_mime_type' => "text/html",
                'created_at' =>$time,
                'parent_id' =>$parentId
            ]
        );
    }

    public function insertFilePdf($url,$parentId){
        $fileModel = new FileModel();
        $time = time();
        return $fileModel->insertGetId(
            [
                'file_name'=>md5($time.$parentId).".pdf",
                'file_url'=>$url,
                'file_ext'=>"pdf",
                'file_mime_type' => "application/pdf",
                'created_at' => $time,
                'parent_id' =>$parentId
            ]
        );
    }

    public function downloadCode(){
        $staffInfo = TokenFuc::getCurrentStaffInfo();
        $token = md5(time()).md5(json_encode($staffInfo)).md5(md5(count($staffInfo)).md5($staffInfo['staff_id']));
        $code = Redis::setex($token,300,1);
        return ResponseFunc::returnJson(
            'ok',
            [
                "code" => $token
            ],
            "获取下载链接code成功",
            ResponseStatusConsts::OK_200_RESPONSE_STATUS
        );
    }





}